package com.tanjun.thirdservice.web.service.wx.impl;

import com.alibaba.fastjson2.TypeReference;
import com.tanjun.common.enums.Method;
import com.tanjun.common.exception.BizException;
import com.tanjun.common.utils.HttpRequestTools;
import com.tanjun.data.components.CloudCacheManager;
import com.tanjun.thirdservice.web.config.WxMiniConfig;
import com.tanjun.thirdservice.web.exceptions.WxErrCode;
import com.tanjun.thirdservice.web.service.wx.WxService;
import com.tanjun.thirdservice.web.service.wx.enums.WxCodeEnum;
import com.tanjun.thirdservice.web.service.wx.request.TokenRequest;
import com.tanjun.thirdservice.web.service.wx.response.TokenResponse;
import com.tanjun.thirdservice.web.service.wx.response.WxBaseResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 微信基础服务
 */
@Service
//@ConditionalOnBean(WxMiniConfig.class)
public class WxServiceImpl implements WxService {

    @Autowired
    private  WxMiniConfig wxMiniConfig;
    @Autowired
    private CloudCacheManager cloudCacheManager;

    /**
     * 获取小程序appId
     *
     * @return
     */
    @Override
    public String getAppid() {
        return wxMiniConfig.getAppId();
    }

    /**
     * 获取小程序secret
     *
     * @return
     */
    @Override
    public String getSecret() {
        return wxMiniConfig.getAppSecurity();
    }

    @Override
    public String getBaseUrl() {
        return wxMiniConfig.getBaseUrl();
    }

    /**
     * 像企业微信发送请求
     *
     * @param url           请求地址
     * @param method        方法
     * @param data          数据
     * @param typeReference 返回数据格式
     * @return 返回数据
     */
    @Override
    public <T extends WxBaseResponse> T doRequest(String url, Method method, Object data, TypeReference<T> typeReference) {
        return doHttp(url, method, data, typeReference);
    }

    @Override
    public <T extends WxBaseResponse> T doRequestWithToken(String url, Method method, Object data, TypeReference<T> typeReference) {
        String token = getToken();
        url = url + "?access_token=" + token;
        return doHttp(url, method, data, typeReference);

    }

    private <T extends WxBaseResponse> T doHttp(String url, Method method, Object data, TypeReference<T> typeReference) {
        for (int i = 0; i < 3; i++) {
            T response = null;
            switch (method) {
                case GET:
                    response = HttpRequestTools.get(url, data, null, typeReference);
                    break;
                case POST:
                    response = HttpRequestTools.postJson(url, data, null, typeReference);
                    break;
            }
            WxCodeEnum code=  WxCodeEnum.valueFrom(response.getErrcode());
            switch (code) {
                case OK:
                    return response;
                case BUSY:
                    break;
                case TOKEN_ERR:
                    clearToken();
                    break;
                default:
                    throw new BizException(WxErrCode.WX_ERR, response.getErrmsg());
            }
        }
        throw new BizException(WxErrCode.WX_ERR);
    }

    /**
     * 获取token
     *
     * @return
     */
    private String getToken() {
        String key = "TOKEN:" + wxMiniConfig.getAppId();
        String token = cloudCacheManager.getString(key);
        if (token != null) {
            return token;
        }
        TokenRequest request = TokenRequest.builder()
                .appid(wxMiniConfig.getAppId())
                .secret(wxMiniConfig.getAppSecurity())
                .grantType("client_credential")
                .build();
        TokenResponse tokenResponse = HttpRequestTools.get(wxMiniConfig.getBaseUrl() + "cgi-bin/token", request, null,
                new TypeReference<TokenResponse>() {
                });
        cloudCacheManager.saveValue(key, tokenResponse.getAccessToken(), tokenResponse.getExpiresIn() - 30);
        return tokenResponse.getAccessToken();
    }

    /**
     * 清除token
     */
    private void clearToken() {
        String key = "TOKEN:" + wxMiniConfig.getAppId();
        cloudCacheManager.delKeys(key);
    }


}
